#ifndef SWAPQUEUE_H
#define SWAPQUEUE_H

#include "global.h"
#include "Event.h"
#include <pthread.h>

namespace ZY {

    /***


    可用事件：
    EVENT_DONE ： 静态事件，当完成一次处理执行循环后触发
    **/

    template <class T>
    class SwapQueue : public EventBase
    {
        public:
            static const int RETURN_RETRY = 2;
            static const int RETURN_TRUE = 0;
            static const int RETURN_FALSE = 1;


            SwapQueue() : lock( PTHREAD_MUTEX_INITIALIZER ) , ready ( PTHREAD_COND_INITIALIZER )
            {

            }

            virtual ~SwapQueue()
            {

            }

            void addToQueue( T unit )
            {
                _waitQueue.push_back( unit );
            }

            bool isSwapQueueEmpty()
            {
                if ( pthread_mutex_trylock( & lock ) != 0 ) {
                    return false;
                }
                if(_waitQueue.empty()&&_swapQueue.empty()&&_execQueue.empty()&&_retryQueue.empty()){
                    pthread_mutex_unlock( & lock );
                    return true;
                }else{
                    pthread_mutex_unlock( & lock );
                    return false;
                }
            }

            void doSwapQueue()
            {
                if ( _waitQueue.empty() ) {
                    return;
                }

                if ( pthread_mutex_trylock( & lock ) != 0 ) {
                    return;
                }
                _swapQueue.splice( _swapQueue.begin() , _waitQueue , _waitQueue.begin() , _waitQueue.end() );

                pthread_cond_signal( & ready );

                pthread_mutex_unlock( & lock );
            }

            void doSwapQueue( list<T> & _waitQueue )
            {
                if ( _waitQueue.empty() ) {
                    return;
                }

                if ( pthread_mutex_trylock( & lock ) != 0 ) {
                    return;
                }
                _swapQueue.splice( _swapQueue.begin() , _waitQueue , _waitQueue.begin() , _waitQueue.end() );

                pthread_cond_signal( & ready );

                pthread_mutex_unlock( & lock );
            }

            bool popExecNode( T &unit )
            {
                if ( _execQueue.empty() ) {
                    pthread_mutex_lock( & lock );
                    _execQueue.swap( _swapQueue );
                    pthread_mutex_unlock( & lock );
                    if ( _execQueue.empty() ) {
                        return false;
                    }
                }
                unit = _execQueue.front();
                _execQueue.pop_front();

                return true;
            }
            void execDeamonStart( bool(*func)(T &unit)  )
            {

                pthread_attr_t thread_attr;

                pthread_attr_init( & thread_attr );
                pthread_attr_setdetachstate( & thread_attr ,  PTHREAD_CREATE_DETACHED ); //设置线程分离状态

                callbackFunction = func;

                pthread_create( & pid , & thread_attr , ( void* (*) (void *) ) & execDeamon , (void*) this );
            }
        protected:
        private:

            static void execDeamon( SwapQueue<T> *obj )
            {
//                T unit;
                int sleep_sec = 0;
                while( true ) {
                    while( ! obj->_execQueue.empty() ) {
                       T& unit = obj->_execQueue.front();
                        try {
                            if ( ! obj->callbackFunction( unit ) ) {
                                obj->_retryQueue.push_back( unit );
                            }
                        } catch ( Exception ) {
                            obj->_retryQueue.push_back( unit );
                        }
                        obj->_execQueue.pop_front();
                    }

                    Event ev;
                    //callStaticEventListener( EVENT::EVENT_DONE , & ev );//可能引起并发同步问题
                    obj->callEventListener(EVENT::EVENT_DONE , &ev);

                    pthread_mutex_lock( & obj->lock );
                    if ( obj->_swapQueue.empty() && !obj->_retryQueue.empty() ) {
                        obj->_execQueue.swap( obj->_retryQueue );
                        sleep_sec = 3;
                    } else {
                        while ( obj->_swapQueue.empty() ) {
                            pthread_cond_wait( & obj->ready , & obj->lock );
                        }
                        obj->_execQueue.swap( obj->_swapQueue );
                        sleep_sec = 0;
                    }
                    pthread_mutex_unlock( & obj->lock );
                    if ( sleep_sec > 0 ) {
                        sleep( sleep_sec );
                    }
                }
            }

            list<T> _waitQueue , _swapQueue , _execQueue , _retryQueue;
            pthread_mutex_t lock;
            pthread_cond_t ready;

            pthread_t pid;
            bool (*callbackFunction)(T &unit);
    };
}
#endif // SWAPQUEUE_H
